package com.abo.yaas.webservice.hibernate;

import javax.persistence.EntityManager;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.Expression;
import javax.persistence.criteria.Order;
import javax.persistence.criteria.Root;
import javax.persistence.metamodel.EntityType;
import javax.persistence.metamodel.SingularAttribute;

/**
 * Data structure class representing a field to sort by and the direction of the
 * sort (ascending or descending). Once created, the instances of this class are
 * immutable.
 */
public final class SortCriteria<T> {
    private final String propertyId;

    private final boolean ascending;

    private final EntityType<T> entityType;

    private final EntityManager em = EntityManagerUtils.getEntityManager();

    private final CriteriaBuilder builder;

    public SortCriteria(String propertyId, boolean ascending, Class<T> classType) {
        assert propertyId != null : "propertyId must not be null";
        this.propertyId = propertyId;
        this.ascending = ascending;
        entityType = em.getMetamodel().entity(classType);
        builder = em.getCriteriaBuilder();
    }

    @SuppressWarnings("unchecked")
    public Order asOrder(Root<T> root) {
        final SingularAttribute<T, ?> attr = (SingularAttribute<T, ?>) entityType
                .getAttribute(propertyId);
        final Expression<?> exp = root.get(attr);
        return ascending ? builder.asc(exp) : builder.desc(exp);
    }

    public Object getPropertyId() {
        return propertyId;
    }

    public boolean isAscending() {
        return ascending;
    }
}
